package top.wilsonlv.jaguar.cloud.auth.extension.sms;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsChecker;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import top.wilsonlv.jaguar.cloud.auth.sdk.token.SmsAuthenticationToken;
import top.wilsonlv.jaguar.cloud.auth.sdk.token.SmsDTO;
import top.wilsonlv.jaguar.cloud.auth.security.UserDetailsServiceImpl;
import top.wilsonlv.jaguar.security.model.SecurityUser;

/**
 * @author lvws
 * @since 2022/1/6
 */
@Slf4j
@Component
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "jaguar.auth.sms", name = "enable", havingValue = "true")
public class SmsAuthenticationProvider implements AuthenticationProvider {

    private final UserDetailsServiceImpl userDetailsService;

    private final UserDetailsChecker userDetailsChecker;

    private final SmsService smsService;


    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsAuthenticationToken token = (SmsAuthenticationToken) authentication;
        if (token.isAuthenticated()) {
            return token;
        }

        SmsDTO smsDTO = token.getSmsDTO();
        smsService.checkSms(smsDTO);

        String principal = (String) token.getPrincipal();

        SecurityUser securityUser;
        try {
            securityUser = userDetailsService.loadUserByUsername(principal);
        } catch (UsernameNotFoundException e) {
            throw new BadCredentialsException("手机号不存在");
        }

        securityUser.setCredentialsNonExpired(true);

        // 检查账号状态
        userDetailsChecker.check(securityUser);

        SmsAuthenticationToken authenticationToken = new SmsAuthenticationToken(securityUser,
                securityUser.getAuthorities());
        authenticationToken.setDetails(token.getDetails());
        return authenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return SmsAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
